{
	//原始数据/对象
	let obj={
		time:'2017-03-11',
		name:'yaozhen',
		_r:123
	}
	//创建代理,用户通过操作代理对象,对原始对象进行读取操作,代理对象可拦截操作做处理
	let monitor=new Proxy(obj,{
		//拦截对象属性的读取
		get(target,key){//对象  属性名
			//将任何属性值中的2017替换成2018
			return target[key].replace('2017','2018')
		},
		//拦截对象属性的设置
		set(target,key,value){//对象  属性名  设置的值
			if(key=='name'){//只允许设置name属性
				return target[key]=value;
			}else{
				return target[key];
			}
		},
		//拦截key in obj操作
		has(target,key){
			if(key=='name'){//只能判断name属性
				return target[key];
			}else{
				return false;
			}
		},
		//拦截删除属性
		deleteProperty(target,key){
			if(key.indexOf('_')>-1){//只允许删除_开头的属性
				delete target[key];
				return true;
			}else{
				return false;
			}
		},
		//拦截获取所有属性,Object.keys,Object.getOwnPropertySymbol等
		ownKeys(target){
			//不返回time属性,从而保护time属性
			return Object.keys(target).filter(item=>item!='time')
		}
	});
	//通过代理访问原始数据
	console.log(monitor.time);//2018-03-11
	monitor.time='2020';//不会变
	monitor.name='何毅';//设置成功
	console.log(monitor);//{time:'2017-03-11',name:'何毅'}
	console.log('name' in monitor,'time' in monitor);//true  false
	delete monitor.time;//删除失败
	delete monitor._r;
	console.log(monitor);//{time: "2017-03-11", name: "何毅"}
	console.log(Object.keys(monitor));//["name"]
}
{
	//Reflect用法与Proxy的拦截API一样
	let obj={
		time:'2017-03-11',
		name:'yaozhen',
		_r:123
	}
	console.log(Reflect.get(obj,"time"));//2017-03-11
	Reflect.set(obj,"time","何毅")
	console.log(obj);//{time: "何毅", name: "yaozhen", _r: 123}
}
{
	//验证规则
	const personValidator={
		name(val){//name属性进行验证,必须是字符串
			return typeof val==='string'
		},
		age(val){//age\属性进行验证,必须是数字且大于18
			return typeof val==='number' && val>18
		}
	}
	//验证函数      目标对象   验证规则
	function validator(target,validator){
		return new Proxy(target,{
			_validator:validator,
			//设置属性验证
			set(target,key,value,proxy){
				//判断属性是否存在
				if(target.hasOwnProperty(key)){
					//获取此属性验证规则
					let va=this._validator[key];
					if(!!va(value)){//验证
						return Reflect.set(target,key,value,proxy);
					}else{
						throw Error('不能设置${key}到${value}');
					}
				}else{
					throw Error('${key}不存在');
				}
			}
		});
	}
	//创建对象
	class Person{
		constructor(name,age) {
		    this.name=name;
		    this.age=age;
		    //调用验证函数,返回一个代理对象,从而可以对象进行额外验证操作
		    //此时用户set操作对象都是通过代理对象,从而被拦截进行数据验证
		    return validator(this,personValidator);
		}
	}
	//这样可以达到业务解耦和高复用性,如果还要添加其他属性验证,只需要在验证规则中添加即可
	const person01=new Person('yaozhen',20);
	console.log(person01);//{name: "yaozhen", age: 20}
	//验证,无法setname属性是一个数字,但是创建对象的时候可以,因为只拦截了set请求
	person01.name=48;//报错:不能设置${key}到${value}
}
